package fudan.se.project.service.advanced.account.user;

import fudan.se.project.controller.request.InvitationAcceptRequest;
import fudan.se.project.controller.request.OnlyIdPropertyRequest;
import fudan.se.project.controller.response.BaseResponse;
import fudan.se.project.controller.response.InvitationsGetResponse;
import fudan.se.project.domain.User;
import fudan.se.project.domain.message.Invitation;
import fudan.se.project.domain.message.Invitation.State;
import fudan.se.project.service.infrastructure.entity.message.InvitationService;
import fudan.se.project.service.infrastructure.func.account.user.InvitationAcceptService;
import fudan.se.project.util.http.ResponseWrapperUtil;
import fudan.se.project.util.user.UserDetailsUtil;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

import static fudan.se.project.repository.projection.InvitationProjection.project;

@Service
public class UserInvitationService {

    private UserDetailsUtil userDetailsUtil;
    private ResponseWrapperUtil responseWrapperUtil;
    private InvitationService invitationService;
    private InvitationAcceptService invitationAcceptService;

    public UserInvitationService(UserDetailsUtil userDetailsUtil,
                                 InvitationService invitationService,
                                 ResponseWrapperUtil responseWrapperUtil,
                                 InvitationAcceptService invitationAcceptService
    ) {
        this.userDetailsUtil = userDetailsUtil;
        this.invitationService = invitationService;
        this.responseWrapperUtil = responseWrapperUtil;
        this.invitationAcceptService = invitationAcceptService;
    }

    @PreAuthorize("hasAuthority('USER')")
    public ResponseEntity<?> invitationsSent(int page) {
        User user = userDetailsUtil.currentUser();
        Page<Invitation> invitationPage = invitationService.getInvitationsBySender(user, page);
        InvitationsGetResponse invitationsGetResponse = new InvitationsGetResponse(
                invitationPage.getTotalPages(),
                project(invitationPage.getContent()));
        return responseWrapperUtil.buildResponseBody(invitationsGetResponse, HttpStatus.OK);


    }

    @PreAuthorize("hasAuthority('USER')")
    public ResponseEntity<?> invitationsReceived(int page) {
        User user = userDetailsUtil.currentUser();
        Page<Invitation> invitationPage = invitationService.getInvitationsByReceiver(user, page);
        InvitationsGetResponse invitationsGetResponse = new InvitationsGetResponse(
                invitationPage.getTotalPages(),
                project(invitationPage.getContent()));
        return responseWrapperUtil.buildResponseBody(invitationsGetResponse, HttpStatus.OK);

    }

    @PreAuthorize("hasAuthority('USER')")
    public ResponseEntity<?> acceptInvitation(InvitationAcceptRequest request) {

        User user = userDetailsUtil.currentUser();
        BaseResponse baseResponse;

        Invitation invitation = invitationService.findById(request.getId());
        if (invitation == null
                || !invitation.getState().equals(State.WAITING)
                || !user.equals(invitation.getReceiver())
                || !invitationAcceptService.process(invitation, request.getTopicIds())) {

            baseResponse = new BaseResponse("Invitation not found!");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.NOT_FOUND);
        } else {
            baseResponse = new BaseResponse("success");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.OK);
        }
    }

    @PreAuthorize("hasAuthority('USER')")
    public ResponseEntity<?> rejectInvitation(OnlyIdPropertyRequest request) {
        Invitation invitation = invitationService.findById(request.getId());
        if (invitation == null) {
            BaseResponse baseResponse = new BaseResponse("arguments error");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.NOT_ACCEPTABLE);
        } else {
            invitation.setState(Invitation.State.REJECTED);
            invitationService.save(invitation);
            BaseResponse baseResponse = new BaseResponse("success");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.OK);
        }
    }
}
